/*
XCommander Extension
http://www.xcommander.ch/
*/

function XCommanderParser(language) {
	this.xcommand = null;
	this.pattern = null;
	this.language = language;
	this.args = {};
	this.echo = [];
	this.suggestions = [];
	this.currentSuggest = [];
}

XCommanderParser.prototype = {
	_getPattern : function(xcommand) {
		var pattern = this._getCommandPattern(xcommand.name);
		if(xcommand.hasOwnProperty("arguments")) {
			for(var i in xcommand.arguments) {
				pattern += this._getRolePattern(xcommand.arguments[i]);
			}
		}
		return pattern;
	},
	_getCommandPattern : function(name) {
		return "^(" + name + ")";
	},
	_getRolePattern : function(arg) {
		if(arg.role == "object") {
			return "(\\s" + this._getNountypePattern(arg) + ")?";
		} else {
			return "(\\s(" + role[arg.role].lang[this.language].join("|") + ")\\s" + this._getNountypePattern(arg) + ")?";
		}
	},
	_getNountypePattern : function(arg) {
		if(arg.nountype instanceof Array) {
			this.suggestions.push(arg.nountype);
			return "(" + arg.nountype.join("|") + ")";
		} else if(arg.nountype == "xcommand") {
			this.suggestions.push(xcommander.ui.panel.getXCommands());
			return nountype[arg.nountype].pattern();
		} else {
			return nountype[arg.nountype].pattern;
		}
	},
	parse : function(input, xcommand) {
		if(this.xcommand != xcommand) {
			this.args = {};
			this.echo = [];
			this.pattern = this._getPattern(xcommand);
			this.suggestions = this.suggestions.reverse();
			this.xcommand = xcommand;
		}
		var regex = new RegExp(this.pattern);
		var matches = regex.exec(input);
		if(matches != null && xcommand.hasOwnProperty("arguments")) {
			this._createArguments(matches, xcommand.arguments);
		}
	},
	_createArguments : function(matches, args) {
		var nextId = 1;
		var id;
		this.args = {};
		this.echo = [];
		this.echo.push("<b>" + matches[1] + "</b>");
		for(var i = 0; i < args.length; i++) {
			if(args[i].role != "object") {
				if(matches[nextId + 2] != undefined) {
					this.echo.push(matches[nextId + 2])
				} else {
					this.echo.push(role[args[i].role].lang[this.language][0]);
				}
			}
			if(args[i].nountype instanceof Array) {
				id = nextId + role[args[i].role].length;
				nextId += role[args[i].role].length;
			} else {
				id = nextId + role[args[i].role].length - 1 + nountype[args[i].nountype].match;
				nextId += role[args[i].role].length - 1 + nountype[args[i].nountype].length;
			}
			if((args.length == 1) && ((args[0].nountype instanceof Array) || (args[0].nountype == "xcommand"))) {
				this.currentSuggest = this.suggestions[0];
			}
			if(matches[id] != undefined) {
				if(i < (args.length - 1)) {
					this.currentSuggest = (args[i + 1].nountype instanceof Array) ? this.suggestions[0] : [];
				}
				this.args[args[i].role] = matches[id].replace(/^\(|\)$/g, "");
				this.echo.push("(<b>" + matches[id].replace(/^\(|\)$/g, "") + "</b>)");
			} else {
				this.echo.push("(<b>" + args[i].label + "</b>)");
			}
		}
	}
}

function XCommanderAutoSuggestion(suggest, input) {
	var TAB = 9;
	var ESC = 27;
	var BACKSPACE = 8;
	this.inputText = null;
	this.match = null;
	this.matchId = 0;
	var elements = [];
	var self = this;
	this.suggestions = [];

	input.attr({
		"autocomplete" : "off"
	});

	input.bind("keydown", function(event) {
		var keyCode = event.keyCode;

		switch(keyCode) {
			case TAB:
				self.catchSuggestion();
				return false;
				break;
			case ESC:
				suggest.val("");
				self.match = "";
				break;
		}
	});

	input.bind("keyup", function(event) {
		var keyCode = event.keyCode;

		switch(keyCode) {
			case TAB:
			case ESC:
				return;
			default:
				if(this.value.length > 0) {
					elements = this.value.split(" ");
					if(elements[elements.length - 1] != "") {
						self.inputText = elements[elements.length - 1];
						self.getMatches();
					}
				} else {
					suggest.val("");
				}
		}
	});

	this.catchSuggestion = function() {
		if(this.match != null) {
			var index = this.match.indexOf(this.inputText);
			var autoComplete = this.match.substring(index + this.inputText.length);
			input.val(input.val() + autoComplete);
			suggest.val("");
			this.match = null;
		}
	}

	this.getMatches = function() {
		for(var key in this.suggestions) {
			var suggestion = this.suggestions[key];
			if(suggestion.toLowerCase().match("^" + this.inputText.toLowerCase())) {
				this.match = suggestion;
				suggest.val($.trim(elements.slice(0, elements.length - 1).join(" ") + " " + suggestion));
				return;
			}
		}
		suggest.val("");
	}
}


var nountype = {
	text : {
		pattern : "(\\(([^)]+)\\)|([A-Za-z0-9äöü_]+))",
		length : 3,
		match : 1
	},
	date_time : {
		pattern : "(((\\d{2}|\\d{1}).(\\d{2}|\\d{1}).(\\d{4}|\\d{2}))?\\s?(([01]?\\d|2[0-3]):([0-5][0-9])))",
		length : 8,
		match : 1
	},
	time : {
		pattern : "(([01]?\\d|2[0-3]):([0-5][0-9]))",
		length : 3,
		match : 1
	},
	xcommand : {
		pattern : function() {
			return "(" + xcommander.ui.panel.getXCommands().join("|") + ")";
		},
		length : 1,
		match : 1,
	}
}

var role = {
	object : {
		length : 2
	},
	source : {
		lang : {
			en : ["from", "in"],
			de : ["von", "ab"]
		},
		length : 3
	},
	goal : {
		lang : {
			en : ["to"],
			de : ["nach", "zu"]
		},
		length : 3
	},
	time : {
		lang : {
			en : ["at"],
			de : ["ab", "am", "um"]
		},
		length : 3
	},
	alias : {
		lang : {
			en : ["as"],
			de : ["als"],
		},
		length : 3
	}
}